package com.bristua.tencent.rtc.sdk.room.business.dao.impl;

import android.content.Context;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;

import com.alibaba.fastjson.JSONObject;
import com.bristua.tencent.rtc.sdk.provider.RtcContainer;
import com.bristua.tencent.rtc.sdk.room.business.JsonRpcResult;
import com.bristua.tencent.rtc.sdk.room.business.api.IRtcLoginApi;
import com.bristua.tencent.rtc.sdk.room.business.callback.IRtcLoginCallback;
import com.bristua.tencent.rtc.sdk.room.business.dao.IRtcLoginDao;
import com.bristua.tencent.rtc.sdk.room.business.dao.exception.RtcLoginException;
import com.hua.yuan.common.https.OkHttpModule;
import com.tencent.imsdk.TIMCallBack;
import com.tencent.imsdk.TIMConnListener;
import com.tencent.imsdk.TIMManager;
import com.tencent.imsdk.TIMSdkConfig;
import com.tencent.imsdk.TIMUserConfig;

import java.io.IOException;
import java.util.Map;

import cm.hua.yuan.common.utils.PreferenceUtils;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject;
import retrofit2.Response;
import retrofit2.Retrofit;

/**
 * @Author: richsjeson.
 * @Description: TODO()
 * @Date:Created in 2019/1/5 8:31 PM.
 * @Modified By:
 */
public class RtcLoginDaoImpl implements IRtcLoginDao {

    private PublishSubject<Integer> mPublishSubject;
    /**
     * 断开RTCRoom SDK
     */
    private PublishSubject<Boolean> mDisconnectSubject;

    public final String TAG = RtcLoginDaoImpl.class.getClass().getName();

    private long mInitializeStartTS;

    private Disposable mDisposable;

    private Retrofit mRetrofit;

    public RtcLoginDaoImpl() {
        mPublishSubject = PublishSubject.create();
        mDisconnectSubject=PublishSubject.create();
        mRetrofit = OkHttpModule.getInstance().getRetrofit();
    }

    @Override
    public void login(@NonNull final Context pContext, @NonNull final Map<String, Object> pMaps) {


        if (mDisposable != null) {
            if (!mDisposable.isDisposed()) {
                mDisposable.dispose();
            }
        }


        mDisposable = Observable.create(new ObservableOnSubscribe<Integer>() {

            @Override
            public void subscribe(ObservableEmitter<Integer> pEmitter) {

                IRtcLoginApi iRtcLoginApi = mRetrofit.create(IRtcLoginApi.class);
                retrofit2.Call<String> call = iRtcLoginApi.login(String.format("%s/%s",RtcContainer.RTC_SERVER_ROOM,"login"), pMaps);
                try {
                    Response<String> response = call.execute();
                    String result = response.body();
                    if(TextUtils.isEmpty(result)){
                        pEmitter.onError(new NullPointerException("解析失败，result为空"));
                    }
                    JsonRpcResult rpcResult=JSONObject.parseObject(result,JsonRpcResult.class);
                    if(rpcResult == null){
                        pEmitter.onError(new NullPointerException("解析失败，result为空"));
                    }
                    String rtcToken=rpcResult.getToken();
                    PreferenceUtils.setString(IRtcLoginDao.RTC_TOKEN,rtcToken);
                    RtcContainer.STORAGE_RTC_TOKEN=rtcToken;
                    pEmitter.onNext(rpcResult.getCode());
                    pEmitter.onComplete();
                } catch (IOException e) {
                    e.printStackTrace();
                    pEmitter.onError(e);
                }

            }

        }).subscribeOn(Schedulers.newThread())
                .map(new Function<Integer, Boolean>() {
                    @Override
                    public Boolean apply(final Integer pCode) {
                        //需要执行一次 SDK 是否断开的检测
                        TIMManager.getInstance().logout(mStopCallback);
                        mDisconnectSubject.subscribe(new Consumer<Boolean>() {
                            @Override
                            public void accept(final Boolean pSuccess) {

                                initializeSdk(pContext,pMaps);
                            }
                        }, new Consumer<Throwable>() {
                            @Override
                            public void accept(final Throwable ex) {
                                initializeSdk(pContext,pMaps);
                            }
                        });
                        return true;
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                        new Consumer<Boolean>() {

                            @Override
                            public void accept(final Boolean pIsSuccess) throws Exception {
                                mDisposable.dispose();
                            }
                        }, new Consumer<Throwable>() {
                            @Override
                            public void accept(final Throwable e) {
                                mDisposable.dispose();
                            }
                        });
    }

    @Override
    public void setRtcLoginCallback(@NonNull final IRtcLoginCallback pCallback) {

      mPublishSubject.subscribe(new Consumer<Integer>() {
            @Override
            public void accept(final Integer pErrorCode) {
                if(pErrorCode == RTC_LOGIN_SUCCESS) {
                    mPublishSubject.onComplete();
                    pCallback.onRtcLoginSuccess(pErrorCode);
                }
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(final Throwable ex){
                mPublishSubject.onComplete();
                pCallback.onRtcLoginError(ex);
            }
        });
    }


    private TIMConnListener mConnListener = new TIMConnListener() {
        @Override
        public void onConnected() {
            Log.i(TAG, String.format("connect success，initialize() time cost %.2f secs", (System.currentTimeMillis() - mInitializeStartTS) / 1000.0));
            mPublishSubject.onNext(RTC_STATUS_ONSUCCESS);
        }

        @Override
        public void onDisconnected(final int pErrorCode, final String pMsg) {
            mPublishSubject.onError(new RtcLoginException(pMsg, pErrorCode));
        }

        @Override
        public void onWifiNeedAuth(final String s) {
            mPublishSubject.onNext(RTC_STATUS_DISCONNECT);
        }
    };

    private TIMCallBack mCallBack = new TIMCallBack() {
        @Override
        public void onError(final int pErrorCode, final String pMsg) {
            Log.i(TAG, "登录失败");
            mPublishSubject.onError(new RtcLoginException(pMsg, pErrorCode));
        }

        @Override
        public void onSuccess() {
            Log.i(TAG, "登录成功");
            mPublishSubject.onNext(RTC_LOGIN_SUCCESS);
        }
    };


    private TIMCallBack mStopCallback = new TIMCallBack() {
        @Override
        public void onError(final int pErrorCode, final String pMsg) {
            mDisconnectSubject.onError(new RtcLoginException(pMsg, pErrorCode));
        }

        @Override
        public void onSuccess() {
            mDisconnectSubject.onNext(true);
        }
    };

    /**
     * 初始化SDK能力
     */
    private void initializeSdk(@NonNull final Context pContext, @NonNull final Map<String, Object> pMaps){
        int appID = (int) pMaps.get(SDK_APP_ID);
        String rtcUserId = (String) pMaps.get(RTC_USER_ID);
        String userSign = (String) pMaps.get(RTC_USER_SIGN);
        TIMSdkConfig timSdkConfig = new TIMSdkConfig(appID);
        timSdkConfig.setServiceEnabled(false);
        mInitializeStartTS = System.currentTimeMillis();
        timSdkConfig.setConnectionListener(mConnListener);
        try {
            if (TIMManager.getInstance().init(pContext, timSdkConfig)) {
                TIMUserConfig timUserConfig = new TIMUserConfig();
                TIMManager.getInstance().login(rtcUserId, userSign, timUserConfig, mCallBack);
            } else {
                mPublishSubject.onNext(RTC_STATUS_ONSUCCESS);
            }
        }catch (java.lang.IllegalThreadStateException e){
            mPublishSubject.onError(e);
        }
    }
}
